package tech.aichan.AiQA.utils;

import jakarta.annotation.Resource;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.Criteria;
import org.springframework.data.elasticsearch.core.query.CriteriaQuery;
import org.springframework.data.elasticsearch.core.query.Query;

import java.util.List;

/**
 * ES 多值查询构建工具
 * @author mengyu
 * @date 2024/06/03 16:03
 */
public class ESQueryBuilder {
    private Criteria criteria = new Criteria();

    public ESQueryBuilder and(Boolean judge, String filed, Object value) {
        if (judge)
            criteria = criteria.and(filed).matches(value);
        return this;
    }

    public <T> ESQueryBuilder in(Boolean judge, String filed, Iterable<T> value) {
        if (judge)
            criteria = criteria.and(filed).in(value);
        return this;
    }

    public <T> ESQueryBuilder notIn(Boolean judge, String filed, Iterable<T> value) {
        if (judge)
            criteria = criteria.and(filed).notIn(value);
        return this;
    }

    public <T> ESQueryBuilder greaterThan(Boolean judge, String filed, T low) {
        if (judge)
            criteria = criteria.and(filed).greaterThan(low);
        return this;
    }

    public <T> ESQueryBuilder greaterThanEqual(Boolean judge, String filed, T low) {
        if (judge)
            criteria = criteria.and(filed).greaterThanEqual(low);
        return this;
    }

    public <T> ESQueryBuilder lessThan(Boolean judge, String filed, T high) {
        if (judge)
            criteria = criteria.and(filed).lessThan(high);
        return this;
    }

    public <T> ESQueryBuilder lessThanEqual(Boolean judge, String filed, T high) {
        if (judge)
            criteria = criteria.and(filed).lessThanEqual(high);
        return this;
    }

    public <T> ESQueryBuilder between(Boolean judge, String filed, T low, T high) {
        if (judge)
            criteria = criteria.and(filed).between(low, high);
        return this;
    }

    public void clear(){
        this.criteria = new Criteria();
    }

    public Query builder() {
        Query criteriaQuery = new CriteriaQuery(criteria);
        clear();
        return criteriaQuery;
    }

    public Query builder(Pageable pageable) {
        Query criteriaQuery = new CriteriaQuery(criteria, pageable);
        clear();
        return criteriaQuery;
    }

    public <R> List<R> get(Class<R> cls, ElasticsearchTemplate elasticsearchTemplate){
        return elasticsearchTemplate.search(this.builder(), cls)
                .map(SearchHit::getContent)
                .toList();
    }

    public <R> Page<R> get(Class<R> cls, ElasticsearchTemplate elasticsearchTemplate, Pageable pageable){
        SearchHits<R> search = elasticsearchTemplate.search(this.builder(pageable), cls);
        List<R> list = search.stream().map(SearchHit::getContent).toList();
        return new PageImpl<>(list,pageable,search.getTotalHits());
    }

}
